package com.cskaoyan.search.service.impl;

import com.cskaoyan.mall.dto.ProductDto;
import com.cskaoyan.search.converter.ProductConverter;
import com.cskaoyan.search.dto.SearchResponse;
import com.cskaoyan.search.entity.ItemDocument;
import com.cskaoyan.search.form.SearchRequest;
import com.cskaoyan.search.repository.ProductRepository;
import com.cskaoyan.search.service.ProductSearchService;
import lombok.extern.slf4j.Slf4j;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.MatchQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.index.query.RangeQueryBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate;
import org.springframework.data.elasticsearch.core.SearchHit;
import org.springframework.data.elasticsearch.core.SearchHits;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;


@Slf4j
@Service
public class ProductSearchServiceImpl implements ProductSearchService {

    @Autowired
    private ProductRepository productRepository;

    @Autowired
    private ProductConverter productConverter;

    @Autowired
    private ElasticsearchRestTemplate restTemplate;

    @Override
    public SearchResponse search(SearchRequest request) {
        SearchResponse<ProductDto> response = new SearchResponse<>();
        NativeSearchQueryBuilder queryBuilder = new NativeSearchQueryBuilder();
        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
        MatchQueryBuilder title = QueryBuilders.matchQuery("title", request.getKey());
        RangeQueryBuilder price = QueryBuilders.rangeQuery("price");
        price.gte(request.getPriceGt());
        price.lte(request.getPriceLte());
        boolQueryBuilder.filter(title).filter(price);
        queryBuilder.withQuery(boolQueryBuilder);
//        前端页码从1开始
        PageRequest pageInfo = PageRequest.of(request.getPage() - 1, request.getSize());
        //        通过sort的值-1 1 进行排序
        if ("-1".equals(request.getSort())) {
            Sort sort1 = Sort.by(Sort.Direction.DESC, "price");
            pageInfo = PageRequest.of(request.getPage() - 1, request.getSize(), sort1);
        }
        if ("1".equals(request.getSort())) {
            Sort sort2 = Sort.by(Sort.Direction.ASC, "price");
            pageInfo = PageRequest.of(request.getPage() - 1, request.getSize(), sort2);
        }
        queryBuilder.withPageable(pageInfo);

//        高亮
        HighlightBuilder highlightBuilder = new HighlightBuilder();
        highlightBuilder.field("title").preTags("<font color=\"red\" size=6>").postTags("</font>");
        queryBuilder.withHighlightBuilder(highlightBuilder);

//        搜索
        SearchHits<ItemDocument> search = restTemplate.search(queryBuilder.build(), ItemDocument.class);
//        结果
        long totalHits = search.getTotalHits();
        List<SearchHit<ItemDocument>> searchHits = search.getSearchHits();
//        list接收结果
        List<ProductDto> productDtoArrayList = new ArrayList<ProductDto>();
//        遍历
        searchHits.forEach(hit -> {
            ItemDocument content = hit.getContent();
//            获取高亮字段
            List<String> title1 = hit.getHighlightField("title");
            content.setTitle(title1.get(0));

            ProductDto productDto = productConverter.item2Dto(content);
            productDtoArrayList.add(productDto);
        });

        response.setData(productDtoArrayList);
        response.setTotal(totalHits);

        return response;
    }

    @Override
    public SearchResponse fuzzySearch(SearchRequest request) {
        // 获取关键字
        String keyword = request.getKey();
//         当前页数为第一页
//        PageRequest.of为JPA中静态方法
//        public static PageRequest of(int page, int size, Sort sort) {
//		        return new PageRequest(page, size, sort);
//	      }
        PageRequest pageRequest = PageRequest.of(0,10);
//         响应
        SearchResponse<ProductDto> response = new SearchResponse<>();

        // 通过关键字查询文档
        Page<ItemDocument> itemDocuments = productRepository.testSearchPage(keyword, pageRequest);

        List<ProductDto> productDtos = new ArrayList<>();
        itemDocuments.forEach(itemDocument -> {
            ProductDto productDto = productConverter.item2Dto(itemDocument);
            productDtos.add(productDto);
        });

        response.setData(productDtos);

        return response;
    }
}
